﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mogre;

namespace WastedMechanics
{
    public class GuiTextLabel : GuiControl
    {
        public TextAreaOverlayElement TextArea;
        public float Padding;
        public bool TextWrap;
        public int LinesCount = 0;
        public int ScrollOffset = 0;

        public GuiTextLabel(string name) : base(name)
        {           
            TextArea = OverlayManager.Singleton.CreateOverlayElement("TextArea", name + "TextArea") as TextAreaOverlayElement;
            TextArea.MetricsMode = GuiMetricsMode.GMM_RELATIVE;
            TextArea.SetDimensions(1.0f, 1.0f);

            Panel.AddChild(TextArea);
        }

        protected override void UpdateInternals()
        {            
            base.UpdateInternals();

            if (Alignment == TextAreaOverlayElement.Alignment.Center)
                TextArea.SetPosition(Width * 0.5f + Padding, Height * 0.5f - TextArea.CharHeight * LinesCount * 0.5f + Padding);
            else
            {
                TextArea.SetPosition(Padding, Padding);
            }            
        }

        public void Scroll()
        {
            ScrollOffset = System.Math.Max(0, ScrollOffset);            
            if (TextWrap)
                TextArea.Caption = BoxTextWrap();            
        }

        protected override bool ProcessInput()
        {
            if (base.ProcessInput())
            {
                if (IsMouseIn)
                {
                    int scroll = System.Math.Sign(Engine.MouseInput.ScrollAmount);                    
                    if (scroll != 0)
                    {                        
                        ScrollOffset -= scroll;
                        Scroll();
                    }
                }

                return true;
            }
            else
                return false;
        }

        protected override void DestroyInternals()
        {
            OverlayManager.Singleton.DestroyOverlayElement(TextArea);
            base.DestroyInternals();
        }

        private string BoxTextWrap()
        {
            string result = "";
            FontPtr font = FontManager.Singleton.GetByName(TextArea.FontName);
            float textWidth = Padding;
            float textHeight = TextArea.CharHeight + Padding;
            float spaceWidth = font.GetGlyphAspectRatio('0') * TextArea.CharHeight / Engine.Camera.AspectRatio ;
            TextArea.SpaceWidth = spaceWidth * 2.0f; // IT has to be * 2.0 because Ogre renders in (-1, 1) coordspace... Ha Ha.
            int wordStart = 0;
            

            for (int i = 0; i < _Caption.Length; i++)
            {
                if (_Caption[i] == 32)
                {
                    textWidth += spaceWidth;
                    wordStart = i;
                }
                else if (_Caption[i] == 10)
                {
                    textHeight += TextArea.CharHeight;

                    // No more height!
                 //   if (textHeight >= TextArea.Height - Padding)
//                        break;

                    textWidth = Padding;
                    wordStart = i;                    
                }
                else
                    textWidth += font.GetGlyphAspectRatio(_Caption[i]) * TextArea.CharHeight / Engine.Camera.AspectRatio;                

                // Oups, We have not enough space for current character
                if (textWidth >= Width - Padding && wordStart != i)
                {
                    textHeight += TextArea.CharHeight;
                    // No more height!
                   // if (textHeight >= Height - Padding)
                     //   break;

                    textWidth = Padding;
          
                    result = result.Remove(wordStart, i - wordStart);
                    result += "\n";                    

                    i = wordStart;
                }
                else
                    result += _Caption[i];                
            }

            int scrolls = ScrollOffset;
            while (scrolls > 0)
            {
                int nlindex = result.IndexOf('\n');
                if (nlindex != -1)
                    result = result.Remove(0, nlindex+1);
                else
                    break;
                scrolls--;
            }

            int maxlines = (int)((Height - 2 * Padding) / TextArea.CharHeight);
            int cp = 0;
            while (cp != -1)
            {
                cp = result.IndexOf('\n', cp);
                maxlines--;
                if (maxlines == 0 && cp != -1)
                {
                    result = result.Remove(cp + 1);
                    break;
                }                
                if (cp != -1)                    
                    cp++;
            }
            
            return result;
        }

        public string FontName
        {
            get
            {
                return TextArea.FontName;
            }
            set
            {
                TextArea.FontName = value;               
            }
        }

        public float CharHeight
        {
            get
            {
                return TextArea.CharHeight;
            }
            set
            {
                TextArea.CharHeight = value;
                FontPtr font = FontManager.Singleton.GetByName(FontName);                
            }
        }

        public ColourValue ColourTop
        {
            get
            {
                return TextArea.ColourTop;
            }
            set
            {
                TextArea.ColourTop = value;                
            }
        }

        public ColourValue ColourBottom
        {
            get
            {
                return TextArea.ColourBottom;
            }
            set
            {
                TextArea.ColourBottom = value;                
            }
        }

        private string _Caption;
        public string Caption
        {
            get
            {
                return _Caption;
            }
            set
            {
                _Caption = value;                         
                LinesCount = 1;
                ScrollOffset = 0;
                string newCaption;
                if (TextWrap)
                    newCaption = BoxTextWrap();
                else
                    newCaption = _Caption;

                int start = 0;
                while ((start = newCaption.IndexOf('\n', start)) != -1)
                {
                    LinesCount++;
                    start++;
                }                         
                                
                TextArea.Caption = newCaption;       
            }
        }               

        public TextAreaOverlayElement.Alignment Alignment
        {
            get
            {
                return TextArea.GetAlignment();                
            }
            set
            {
                TextArea.SetAlignment(value);                                
            }
        }
        public new float Height
        {
            get
            {
                return Panel.Height;
            }
            set
            {
                base.Height = value;
                TextArea.Height = value;
            }
        }

        public new float Width
        {
            get
            {
                return Panel.Width;
            }
            set
            {
                base.Width = value;                
                TextArea.Width = value;
            }
        }
    }

}
